package com.bjpowernode.service.impl;


import com.alibaba.fastjson.JSONObject;
import com.bjpowernode.search.SearchProduct;
import com.bjpowernode.service.SearchService;
import com.bjpowernode.vo.PageInfo;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.Index;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class SearchServiceImpl implements SearchService {

    @Resource
    private RestHighLevelClient client;

    @Override
    public PageInfo list(Integer pageNo, Integer pageSize, String name) throws Exception {
        List<SearchProduct> list = new ArrayList<>();
        Integer start = 0;
        //掠过几条 查几条
        start = (pageNo - 1) * pageSize;
        Long total = 0L;

        //高亮显示
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.requireFieldMatch(false).field("name").preTags("<strong style='color:#FF0000'>").postTags("</strong>");
        //要查询的索引
        SearchRequest request = new SearchRequest("product");

        //构建条件查询对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //分页查询
        searchSourceBuilder.highlighter(highlightBuilder).from(start).size(pageSize);

        if (StringUtils.isNoneBlank(name)){
            //模糊查询，不为空则根据名字查
            searchSourceBuilder.query(QueryBuilders.matchQuery("name",name));
        }else {
            //查询判断是否名字为空值查全部（表示不模糊查询）
            searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        }
        //构建请求对象，将构建好的条件查询查询对象放入请求对象中
        request.source(searchSourceBuilder);
        //发送请求执行查询，返回请求响应，我们需要的数据都包裹在response中
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        //从相应response中获取数据
        //获取total，注意total总条数是在第一层的hits中
        SearchHits hits = response.getHits();
        total = hits.getTotalHits().value;

        //获取数据，数据在第二层his中
        SearchHit[] hitsArray = hits.getHits();
        //遍历数据，因为查分页到的是多条数据，所以进行单独遍历处理
        for (SearchHit hit : hitsArray) {
            //创建对应实体类对象，将遍历出的单条数据反序列化为json对象，将对象中属性封装到实体类中
            SearchProduct content = JSONObject.parseObject(hit.getSourceAsString(), SearchProduct.class);
            //获取高亮数据（hit.getHighlightFields()返回一个Map<String, HighlightField>，其中包含了该hit对象的所有高亮字段。）
            Map<String, HighlightField> map = hit.getHighlightFields();
            //获取高量数据具体字段的值
            HighlightField field = map.get("name");
            //将高亮数据替换到实体类对象中
            content.setName(field.getFragments()[0].toString());
            //将数据（以对象的形式）添加到集合中
            list.add(content);
        }
        //返回数据（分页信息）
        return new PageInfo(list, pageNo, pageSize, total);
    }

    //添加
    @Override
    public boolean add(String id, String name, BigDecimal price, String src) throws Exception {
        //创建对象保存要添加的数据
        SearchProduct product = new SearchProduct(id, name, price, src);
        //创建请求对象（添加请求对象），以及要给具体索引添加的数据
        IndexRequest request = new IndexRequest("product");
        //设置设置添加数据的id（此id不是商品id而是索引下的数据条id）
        request.id(id);
        //构建请求条件，将数据序列化为json字符串，并设置数据类型
        request.source(JSONObject.toJSONString(product), XContentType.JSON);
        //发送请求
        client.index(request,RequestOptions.DEFAULT);
        //成功返回true
        return true;
    }

    @Override
    public boolean update(String id, String name, BigDecimal price, String src) throws Exception {
        SearchProduct product = new SearchProduct(id, name, price, src);
        //创建修改请求对象，参数为要求改的索引和索引中具体的数据条的id
        UpdateRequest request = new UpdateRequest("product",id);
        //设置修改的数据
        request.doc(JSONObject.toJSONString(product),XContentType.JSON);
        //发送请求
        client.update(request,RequestOptions.DEFAULT);
        return true;
    }

    @Override
    public boolean del(String id) throws Exception {
        DeleteRequest request = new DeleteRequest("product",id);
        client.delete(request,RequestOptions.DEFAULT);
        return true;
    }
}

